package cn.quevo.beetlsql;

import cn.quevo.beetlsql.dao.BasicRepository;
import cn.quevo.core.entity.DoEntity;
import cn.quevo.core.entity.PageResult;
import cn.quevo.core.entity.exp.MapPageResult;
import cn.quevo.core.entity.query.Query;
import cn.quevo.core.entity.query.QueryPage;
import cn.quevo.core.enums.ResultStatusEnum;
import cn.quevo.core.exception.CustomException;
import cn.quevo.core.lang.StringUtils;
import org.beetl.sql.core.BeetlSQLException;
import org.beetl.sql.core.SQLReady;
import org.beetl.sql.core.annotatoin.Table;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import java.util.List;
import java.util.Map;

/**
 * 基础Dao实现
 *
 * @param <T> Do，和数据库对应的持久化对象
 * @param <Q> Query，查询对象
 * @author July july_sky@foxmail.com
 * @version 1.0
 * @date 2017年12月14日 下午11:25:35
 * @Copyright ©2015-2035 湘豫(北京)科技有限公司. All Rights Reserved.
 */
public abstract class BasicDao<T extends DoEntity, Q extends QueryPage> implements BasicRepository<T, Q> {

    private final Logger log = LoggerFactory.getLogger(BasicDao.class);
    private final static String REMOVE_SQL = "UPDATE {} SET last_time = NOW(),last_id = ?,valid_yn = 'N' WHERE id = ? AND record_owner_id = ? AND valid_yn = 'Y'";
    private final static String DELETE_SQL = "DELETE FROM {} WHERE id = ? AND record_owner_id = ?";
    private final static String GET_VER_NUM_SQL = "SELECT ver_num FROM {} WHERE id = ?";
    private final static String ENABLED_SQL = "UPDATE {} SET last_time = NOW(),last_id = ?,ver_num = ver_num + 1,enabled_yn = 'Y' WHERE id = ? AND record_owner_id = ? AND valid_yn = 'Y' AND enabled_yn = 'N'";
    private final static String DISABLED_SQL = "UPDATE {} SET last_time = NOW(),last_id = ?,ver_num = ver_num + 1,enabled_yn = 'N' WHERE id = ? AND record_owner_id = ? AND valid_yn = 'Y' AND enabled_yn = 'Y'";

    @Autowired
    @Qualifier("beetlSqlFactory")
    private BeetlSQLFactory beetlSqlFactory;

    protected BeetlSQLFactory getBeetlSqlFactory() {
        return beetlSqlFactory;
    }

    @Override
    public Integer create(T entity) {
        return this.beetlSqlFactory.createObject(getSqlId("create"), entity, "id");
    }

    @Override
    public Integer update(T entity) {
        try {
            Long verNum = this.getVerNum(entity);
            if (!StringUtils.isBlank(verNum)) {
                entity.setVerNum(verNum);
            }
        } catch (CustomException e) {
            log.warn("获取版本号失败", e);
        }
        return this.beetlSqlFactory.updateObject(getSqlId("update"), entity);
    }

    @Override
    public Integer remove(T entity) {
        String sql = this.getRemoveSql(entity);
        if (StringUtils.isBlank(entity.getVerNum())) {
            return this.beetlSqlFactory.getSqlManager().executeUpdate(new SQLReady(sql, entity.getOperatorId(), entity.getId(), entity.getRecordOwnerId()));
        }
        return this.beetlSqlFactory.getSqlManager().executeUpdate(new SQLReady(sql, entity.getOperatorId(), entity.getId(), entity.getRecordOwnerId(), entity.getVerNum()));
    }

    @Override
    public Integer delete(T entity) {
        String sql = this.getDeleteSql(entity);
        if (StringUtils.isBlank(entity.getVerNum())) {
            return this.beetlSqlFactory.getSqlManager().executeUpdate(new SQLReady(sql, entity.getId(), entity.getRecordOwnerId()));
        }
        return this.beetlSqlFactory.getSqlManager().executeUpdate(new SQLReady(sql, entity.getId(), entity.getRecordOwnerId(), entity.getVerNum()));
    }

    /**
     * 获取单个对象
     *
     * @param query
     * @param clazz
     * @return
     * @throws CustomException
     * @author July july_sky@foxmail.com
     * @date 2017年12月18日 下午3:54:25
     */
    protected <E> E getSinge(Query query, Class<E> clazz) {
        return this.beetlSqlFactory.getObject(getSqlId("getSinge"), query, clazz);
    }
    /**
     * 获取单个对象
     *
     * @param query
     * @return
     * @throws CustomException
     * @author July july_sky@foxmail.com
     * @date 2017年12月18日 下午3:54:25
     */
    protected Map<String,Object> getObject(Query query) {
        return this.beetlSqlFactory.getObject(getSqlId("getSinge"), query);
    }

    /**
     * 获取列表记录
     *
     * @param query
     * @param clazz
     * @return
     * @throws CustomException
     * @author July july_sky@foxmail.com
     * @date 2017年12月18日 下午3:55:08
     */
    public  <E> List<E> getList(Query query, Class<E> clazz) {
        return this.beetlSqlFactory.selectList(getSqlId("getList"), clazz, query);
    }

    /**
     * 获取列表记录
     *
     * @param query
     * @return
     * @throws CustomException
     * @author July july_sky@foxmail.com
     * @date 2017年12月18日 下午3:55:08
     */
    public List<Map<String,Object>> getMapList(Query query) {
        return this.beetlSqlFactory.selectList(getSqlId("getList"), query);
    }

    /**
     * 分页获取记录集
     *
     * @param query
     * @return
     * @throws CustomException
     * @author July july_sky@foxmail.com
     * @date 2017年12月18日 下午3:55:57
     */
    protected <E> PageResult<E> getPage(QueryPage query, Class<E> clazz) {
        return this.beetlSqlFactory.getPageResult(getSqlId("getList"), getSqlId("getCount"), query, clazz);
    }

    /**
     * 分页获取记录集
     *
     * @param query
     * @return
     * @throws CustomException
     * @author July july_sky@foxmail.com
     * @date 2017年12月18日 下午3:55:57
     */
    protected MapPageResult getMapPage(QueryPage query) {
        return this.beetlSqlFactory.getPageResult(getSqlId("getList"), getSqlId("getCount"), query);
    }

    /**
     * 启用记录
     *
     * @param entity
     * @return
     * @author July july_sky@foxmail.com
     * @date 2018-04-19 16:07:33
     * @Copyright ©2015-2035 湘豫(北京)科技有限公司. All Rights Reserved.
     * @version 1.0
     */
    protected Integer updateEnabled(DoEntity entity) {
        String sql = this.getEnabledSql(entity);
        if (StringUtils.isBlank(entity.getVerNum())) {
            return this.beetlSqlFactory.getSqlManager().executeUpdate(new SQLReady(sql, entity.getOperatorId(), entity.getId(), entity.getRecordOwnerId()));
        }
        return this.beetlSqlFactory.getSqlManager().executeUpdate(new SQLReady(sql, entity.getOperatorId(), entity.getId(), entity.getRecordOwnerId(), entity.getVerNum()));
    }

    /**
     * 禁用记录
     *
     * @param entity
     * @return
     * @author July july_sky@foxmail.com
     * @date 2018-04-19 16:08:12
     * @Copyright ©2015-2035 湘豫(北京)科技有限公司. All Rights Reserved.
     * @version 1.0
     */
    protected Integer updateDisabled(DoEntity entity) {
        String sql = this.getDisabledSql(entity);
        if (StringUtils.isBlank(entity.getVerNum())) {
            return this.beetlSqlFactory.getSqlManager().executeUpdate(new SQLReady(sql, entity.getOperatorId(), entity.getId(), entity.getRecordOwnerId()));
        }
        return this.beetlSqlFactory.getSqlManager().executeUpdate(new SQLReady(sql, entity.getOperatorId(), entity.getId(), entity.getRecordOwnerId(), entity.getVerNum()));
    }

    /**
     * 获取版本号
     *
     * @param entity
     * @return
     * @author July july_sky@foxmail.com
     * @date 2018年3月18日 下午10:06:09
     */
    public Long getVerNum(DoEntity entity) {
        List<Long> vers = this.beetlSqlFactory.getSqlManager().execute(new SQLReady(this.formatGetVerNumSql(entity), entity.getId()), Long.class);
        if (StringUtils.isEmpty(vers) || vers.size() > 1) {
            throw new CustomException(ResultStatusEnum.RECORD_NOT_EXISTS);
        }
        return vers.get(0);
    }


    /**
     * 获取真实的SQL ID
     *
     * @param sqlId
     * @return
     * @author July july_sky@foxmail.com
     * @date 2017年12月13日 下午5:35:46
     */
    protected String getSqlId(String sqlId) {
        return getSqlPre().concat(sqlId);
    }

    /**
     * 获取Table名称
     *
     * @param entity
     * @return
     * @author July july_sky@foxmail.com
     * @date 2018-04-09 21:54:16
     * @Copyright ©2015-2035 湘豫(北京)科技有限公司. All Rights Reserved.
     * @version 1.0
     */
    protected String getTableName(DoEntity entity) {
        Table table = entity.getClass().getAnnotation(Table.class);
        if (table == null || StringUtils.isBlank(table.name())) {
            return null;
        }
        return table.name();
    }

    /**
     * 格式化获取版本号SQL
     *
     * @param entity
     * @return
     * @author July july_sky@foxmail.com
     * @date 2018-04-09 22:24:13
     * @Copyright ©2015-2035 湘豫(北京)科技有限公司. All Rights Reserved.
     * @version 1.0
     */
    protected String formatGetVerNumSql(DoEntity entity) {
        String tableName = this.getTableName(entity);
        if (StringUtils.isBlank(tableName)) {
            throw new CustomException(ResultStatusEnum.TABLE_OR_VIEW_NOT_EXISTS);
        }
        return StringUtils.format(GET_VER_NUM_SQL, "{}", tableName);
    }

    /**
     * 格式化SQL
     *
     * @param entity
     * @param sql
     * @return
     * @author July july_sky@foxmail.com
     * @date 2018-04-19 15:40:37
     * @Copyright ©2015-2035 湘豫(北京)科技有限公司. All Rights Reserved.
     * @version 1.0
     */
    protected String formatSqlByTable(DoEntity entity, final String sql) {
        String tableName = this.getTableName(entity);
        if (StringUtils.isBlank(tableName)) {
            throw new CustomException(ResultStatusEnum.TABLE_OR_VIEW_NOT_EXISTS);
        }
        entity.setVerNum(this.getVerNum(entity));
        if (StringUtils.isBlank(entity.getVerNum())) {
            return StringUtils.format(sql, "{}", tableName);
        }
        return StringUtils.format(sql, "{}", tableName) + " AND ver_num = ?";
    }

    /**
     * 获取逻辑删除SQL
     *
     * @param entity
     * @return
     * @author July july_sky@foxmail.com
     * @date 2018-04-09 22:09:47
     * @Copyright ©2015-2035 湘豫(北京)科技有限公司. All Rights Reserved.
     * @version 1.0
     */
    protected String getRemoveSql(DoEntity entity) {
        return this.formatSqlByTable(entity, REMOVE_SQL);
    }

    /**
     * 获取物理删除SQL
     *
     * @param entity
     * @return
     * @author July july_sky@foxmail.com
     * @date 2018-04-09 22:30:47
     * @Copyright ©2015-2035 湘豫(北京)科技有限公司. All Rights Reserved.
     * @version 1.0
     */
    protected String getDeleteSql(DoEntity entity) {
        return this.formatSqlByTable(entity, DELETE_SQL);
    }

    /**
     * 启用
     *
     * @param entity
     * @return
     * @author July july_sky@foxmail.com
     * @date 2018-04-19 15:42:32
     * @Copyright ©2015-2035 湘豫(北京)科技有限公司. All Rights Reserved.
     * @version 1.0
     */
    protected String getEnabledSql(DoEntity entity) {
        return this.formatSqlByTable(entity, ENABLED_SQL);
    }

    /**
     * 禁用
     *
     * @param entity
     * @return
     * @author July july_sky@foxmail.com
     * @date 2018-04-19 15:43:01
     * @Copyright ©2015-2035 湘豫(北京)科技有限公司. All Rights Reserved.
     * @version 1.0
     */
    public String getDisabledSql(DoEntity entity) {
        return this.formatSqlByTable(entity, DISABLED_SQL);
    }
}
